﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;

namespace Summerset.Isbndb.Authors
{
    /// <summary>
    /// Represents information about an author returned from the authors collection.
    /// </summary>
    public sealed class AuthorElement : ResponseElementBase
    {
        #region Constructor + Overridden Properties

        /// <summary>
        /// Initializes a new instance of the <see cref="AuthorElement"/> class.
        /// </summary>
        /// <param name="element">The xml element containing the underlying information for this instance.</param>
        public AuthorElement(XmlElement element) : base(element)
        { }

        /// <summary>
        /// Gets the element name that is expected by the constructor of this object.
        /// If the provided element name does not match the expected element name, an exception will be thrown.
        /// </summary>
        protected override string ExpectedElementName
        {
            get { return "AuthorData"; }
        }

        #endregion
        #region Common Response Properties

        /// <summary>
        /// Gets the ISBNDB.com-specific ID for this author.
        /// </summary>
        public string AuthorId
        {
            get { return _element.Attributes["person_id"].Value; }
        }

        /// <summary>
        /// Free form text that represents this author.
        /// </summary>
        public string Name
        {
            get { return _element.InnerText; }
        }

        #endregion
        #region Additional Response Properties

        /// <summary>
        /// OPTIONAL RESULT: Gets additional information about this author.
        /// This value will be null unless the Details additional result field was requested.
        /// This must be explicitly requested from the api by providing the 'details' argument with the request.
        /// </summary>
        public AuthorElementDetail Details
        {
            get
            {
                if (_details == null)
                {
                    var detailNode = _element.SelectSingleNode("/Details");

                    if (detailNode != null)
                        _details = new AuthorElementDetail((XmlElement)detailNode);
                }

                return _details;
            }
        }
        AuthorElementDetail _details;
       
        /// <summary>
        /// OPTIONAL RESULT: Gets a list of categories this author is listed in.
        /// This must be explicitly requested from the api by providing the 'categories' argument with the request.
        /// </summary>
        public ReadOnlyCollection<AuthorElementCategory> Categories
        {
            get
            {
                if (_categories == null)
                {
                    var categoryNodes = _element.SelectNodes("/Categories/Category");

                    if (categoryNodes != null)
                    {
                        var collection = new Collection<AuthorElementCategory>();

                        foreach (XmlElement categoryNode in categoryNodes)
                            collection.Add(new AuthorElementCategory(categoryNode));                        

                        _categories = new ReadOnlyCollection<AuthorElementCategory>(collection);
                    }
                }

                return _categories;
            }
        }
        ReadOnlyCollection<AuthorElementCategory> _categories;

        /// <summary>
        /// OPTIONAL RESULT: Gets a list of subjects this author has books about.
        /// This must be explicitly requested from the api by providing the 'subjects' argument with the request.
        /// </summary>
        public ReadOnlyCollection<AuthorElementSubject> Subjects
        {
            get
            {
                if (_subjects == null)
                {
                    var subjectNodes = _element.SelectNodes("/Subjects/Subject");

                    if (subjectNodes != null)
                    {
                        var collection = new Collection<AuthorElementSubject>();

                        foreach (XmlElement subjectNode in subjectNodes)
                            collection.Add(new AuthorElementSubject(subjectNode));

                        _subjects = new ReadOnlyCollection<AuthorElementSubject>(collection);
                    }
                }

                return _subjects;
            }
        }
        ReadOnlyCollection<AuthorElementSubject> _subjects;

        #endregion
    }
}
